#include "statusactor.h"
#include "effectbase.h"
#include <assert.h>
#include "deviceactor.h"
#include "datamanager.h"
#include "actorfactory.h"
#include "map.h"
#include "stringproperty.h"
//#include "htutility.h"
#include "datatypedefine.h"

namespace VrDataCore
{
	StatusActor::StatusActor():_deviceActor(NULL)
	{
		setClassName(CLASS_STATUS);
	}

	StatusActor::~StatusActor()
	{}

	void StatusActor::buildPropertyMap()
	{	
		addProperty(new StringProperty<StatusActor>(XML_ELEMENT_DATATYPE_STRING,
			"EffectList","",this,&StatusActor::setEffectActorIdList,
			&StatusActor::getEffectActorIdList,"",""));
	}

	void StatusActor::setEffectActorIdList(QString idlist)
	{
		_actorPropertyArray = idlist;
	}

	QString StatusActor::getEffectActorIdList()
	{
		_actorPropertyArray = "";
		osg::ref_ptr<CoreBase::ActorBase> actor;
		foreach(actor,_listEffectActor)
		{
			_actorPropertyArray = _actorPropertyArray + "," + actor->getId();
		}
		return _actorPropertyArray;
	}

	bool StatusActor::isContainsEffect(CoreBase::ActorBase* actor)
	{
		QList<osg::ref_ptr<CoreBase::ActorBase>>::iterator iter = _listEffectActor.begin();
		for(;iter!=_listEffectActor.end();iter++)
		{
			if((*iter).get() == actor)
			{
				return true;
			}
		}
		return false;
	}

	bool StatusActor::isContainsEffect(const QString& drawableid,const QString& effectname)
	{
		QList<CoreBase::ActorBase*> effectlist = getMeshDrawableActorEffect(drawableid);
		CoreBase::ActorBase* actor;
		foreach(actor,effectlist)
		{
			if(actor->getClassName() == effectname)
				return true;
		}
		return false;
	}

	CoreBase::ActorBase* StatusActor::getEffectActor(const QString& drawableid,const QString& effectname)
	{
		QList<CoreBase::ActorBase*> effectlist = getMeshDrawableActorEffect(drawableid);
		CoreBase::ActorBase* actor;
		foreach(actor,effectlist)
		{
			if(actor->getClassName() == effectname)
				return actor;
		}
		return NULL;
	}

	void StatusActor::addEffectActor(CoreBase::ActorBase* effect,CoreBase::ActorBase* bindingtarget)
	{
		if(!isContainsEffect(effect))
		{
			osg::ref_ptr<CoreBase::ActorBase> addeffect = effect;
			_listEffectActor.push_back(addeffect);
			if(bindingtarget!=NULL)
			{
				dynamic_cast<EffectBase*>(effect)->bindingMeshDrawableActor(bindingtarget);
			}
		}
	}

	void StatusActor::removeEffectActor(CoreBase::ActorBase* effect,CoreBase::ActorBase* bindingtarget)
	{
		if(isContainsEffect(effect))
		{
			if(bindingtarget!=NULL)
			{
				dynamic_cast<EffectBase*>(effect)->unApply(dynamic_cast<MeshDrawableActor*>(bindingtarget));
				dynamic_cast<EffectBase*>(effect)->removeBindingMeshDrawableActor(bindingtarget);
				if(getBelongMap())
					getBelongMap()->removeActor(*effect);
				_listEffectActor.removeOne(effect);
				//refresh
				_deviceActor->setValidStatusActor(this);
			}
		}
	}

	void StatusActor::removeAllEffectActors()
	{
		QList<osg::ref_ptr<CoreBase::ActorBase>> mchildlist = _deviceActor->getAllMeshDrawableActor();
		QList<osg::ref_ptr<CoreBase::ActorBase>>::iterator mchilditer = mchildlist.begin();
		for(;mchilditer!=mchildlist.end();mchilditer++)
		{
			removeMeshDrawableActor((*mchilditer).get());
		}
	}

	void StatusActor::removeMeshDrawableActor(CoreBase::ActorBase* drawable)
	{
		QList<CoreBase::ActorBase*> effectlist = getMeshDrawableActorEffect(drawable->getId());
		for(int i=0;i<effectlist.size();i++)
		{
			removeEffectActor(effectlist.at(i),drawable);
		}
	}

	void StatusActor::addMeshDrawableActor(CoreBase::ActorBase* drawable)
	{
		QString transformstringvalue = "";
		QString rotationstringvalue = "";
		CoreBase::ActorBase* defaultstatus = _deviceActor->getDefaultStatusActor();
		QList<CoreBase::ActorBase*> effectlist = dynamic_cast<StatusActor*>(defaultstatus)->getMeshDrawableActorEffect(drawable->getId());
		CoreBase::ActorBase* effectactor;
		foreach(effectactor,effectlist)
		{
			CoreBase::ActorProperty* trans = effectactor->getProperty(ACTOR_PROPERYT_TRANSLATION);
			if(trans!=NULL)
			{
				transformstringvalue = trans->toQString();
			}
			CoreBase::ActorProperty* rota = effectactor->getProperty(ACTOR_PROPERYT_ROTATION);
			if(rota!=NULL)
			{
				rotationstringvalue = rota->toQString();
			}
		}
		osg::ref_ptr<CoreBase::ActorBase> translation = VrDataCore::DataManager::GetInstance().getActorFactory()->createActorByDataType(CLASS_EFFECT_TRANSLATION);
		osg::ref_ptr<CoreBase::ActorBase> rotation = VrDataCore::DataManager::GetInstance().getActorFactory()->createActorByDataType(CLASS_EFFECT_ROTATION);
		dynamic_cast<EffectBase*>(translation.get())->bindingMeshDrawableActor(drawable);
		translation->getProperty(ACTOR_PROPERYT_TRANSLATION)->fromString(transformstringvalue);
		dynamic_cast<EffectBase*>(rotation.get())->bindingMeshDrawableActor(drawable);
		rotation->getProperty(ACTOR_PROPERYT_ROTATION)->fromString(rotationstringvalue);
		_listEffectActor.push_back(translation);
		_listEffectActor.push_back(rotation);
	}

	QList<osg::ref_ptr<CoreBase::ActorBase>> StatusActor::getAllEffectActors()
	{
		return _listEffectActor;
	}

	void StatusActor::addToMapEnd(CoreBase::Map* map)
	{
		QList<osg::ref_ptr<CoreBase::ActorBase>>::Iterator iter = _listEffectActor.begin();
		for(;iter!=_listEffectActor.end();++iter)
		{
			map->addActor(*(*iter).get());
		}
	}

	void StatusActor::removeFromMapEnd(CoreBase::Map* map)
	{
		QList<osg::ref_ptr<CoreBase::ActorBase>>::Iterator iter = _listEffectActor.begin();
		for(;iter!=_listEffectActor.end();++iter)
		{
			map->removeActor(*(*iter).get());
		}
	}

	QList<CoreBase::ActorBase*> StatusActor::getMeshDrawableActorEffect(const QString& drawableid)
	{
		QList<CoreBase::ActorBase*> returnvalue;
		osg::ref_ptr<CoreBase::ActorBase> actor;
		foreach(actor,_listEffectActor)
		{
			if(dynamic_cast<EffectBase*>(actor.get())->getBindingActorId() == drawableid)
			{
				returnvalue.push_back(actor.get());
			}
		}
		return returnvalue;
	}

	void StatusActor::onMapLoadEnd(CoreBase::Map* map)
	{
		StatusBase::onMapLoadEnd(map);
		QStringList mlist = _actorPropertyArray.split(',');
		if(map)
		{
			for (int i=0;i<mlist.size();i++)
			{
				QString stringactionID = mlist[i].trimmed();
				if(stringactionID!="")
				{
					CoreBase::ActorBase* actor = map->getActorById(stringactionID);
					if (actor)
					{
						dynamic_cast<EffectBase*>(actor)->onMapLoadEnd(map);
						addEffectActor(actor,NULL);
					}
				}
			}
		}
	}

	void StatusActor::setDeviceActor(DeviceActor* deivce)
	{
		_deviceActor = deivce;
	}

	DeviceActor* StatusActor::getDeviceActor() const
	{
		return _deviceActor;
	}

	void StatusActor::setEffectEnable(bool enable)
	{
		_isEnable = enable;
		QList<osg::ref_ptr<CoreBase::ActorBase>> mchildlist = _deviceActor->getAllMeshDrawableActor();
		QList<osg::ref_ptr<CoreBase::ActorBase>>::iterator mchilditer = mchildlist.begin();
		for(;mchilditer!=mchildlist.end();mchilditer++)
		{
			dynamic_cast<MeshDrawableActor*>((*mchilditer).get())->setUseDefaultStateSet(_isDefaultStatus);
			osg::ref_ptr<CoreBase::ActorBase> actor;
			foreach(actor,_listEffectActor)
			{
				if(dynamic_cast<EffectBase*>(actor.get())->getBindingActorId() ==(*mchilditer)->getId())
				{
					if(_isEnable)
						dynamic_cast<EffectBase*>(actor.get())->apply((*mchilditer).get());
					else
						dynamic_cast<EffectBase*>(actor.get())->unApply((*mchilditer).get());
				}
			}
		}
	}
}